package com.ld.security.auth.server.base.api;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.ShearCaptcha;
import cn.hutool.core.lang.Console;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.ld.security.auth.common.base.constants.JwtTokenConstant;
import com.ld.security.auth.common.base.po.LoginPo;
import com.ld.security.auth.common.base.vo.TokenVo;
import com.ld.security.auth.common.rpc.po.TokenPo;
import com.ld.security.auth.server.base.auth.UserAuth;
import com.ld.security.auth.server.base.po.UserNameAndTokenStatus;
import com.ld.security.auth.server.modules.ge.service.IGeModelService;
import com.ld.security.auth.server.modules.sys.api.SysTokenApi;
import com.ld.security.auth.server.modules.sys.entity.SysToken;
import com.ld.security.auth.server.modules.sys.service.ISysTokenService;
import com.ld.security.common.core.anno.ApiLog;
import com.ld.security.common.core.anno.MockKey;
import com.ld.security.common.core.base.po.EntitysPo;
import com.ld.security.common.core.base.vo.DataVo;
import com.ld.security.common.core.exception.ApiException;
import com.ld.security.common.core.util.CrptUtil;
import com.ld.security.common.core.util.ReflectionUtil;
import com.ld.security.common.core.util.UuidUtil;
import com.ld.security.common.shiro.constants.ShiroCacheConstants;
import com.ld.security.common.shiro.util.RespUtil;
import com.ld.security.common.shiro.util.SessionUtil;
import com.ld.security.common.shiro.vo.UserInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;

@RestController
@RequestMapping("/auth/authUser")
@Api(tags="用户授权中心")
@MockKey(path = "mock/")
public class AuthUserApi  {

    @Autowired
    private UserAuth userAuth;

    @Autowired
    private ISysTokenService iSysTokenService;


    String loginUrl="http://127.0.0.1:6080/oauth/token";

    private static String captchaKey="captcha";

    @Autowired
    private  IGeModelService iGeModelService;

    @Autowired
    SysTokenApi sysTokenApi;

    @Autowired
    SessionDAO sessionDAO;

    @RequestMapping(value="/createCode",method=RequestMethod.GET)
    @ApiOperation("创建验证码")
    @SneakyThrows

    public void createCode() {
        ShearCaptcha captcha = SessionUtil.get(captchaKey);
        if(captcha == null) {
            captcha= CaptchaUtil.createShearCaptcha(200, 100, 4, 4);
            SessionUtil.set(captchaKey, captcha);
        }
        captcha.createCode();
        ServletOutputStream out = SessionUtil.getResponse().getOutputStream();
        captcha.write(out);
        out.close();
    }


    @RequestMapping(value = "/loginByUsername",method = RequestMethod.POST)
    @ApiLog(label = "用户登录",logType = "登录",value = "${po.username} 执行登录操作")

    public DataVo<TokenVo> loginByUsername(@Validated @RequestBody LoginPo po) {
        CrptUtil.encrpt(po);
        Subject subject =  SecurityUtils.getSubject();
        if(!subject.isAuthenticated()){


            UsernamePasswordToken token = new UsernamePasswordToken(po.getUsername(),po.getPassword());
            subject.login(token);
            this.getUserInfo();


            UserNameAndTokenStatus q =   new UserNameAndTokenStatus(po.getUsername(),JwtTokenConstant.tokenStatus.login_auth);
            List<SysToken> sysTokenList =  iSysTokenService.all(q);

            for (SysToken sysToken1 : sysTokenList) {
                sysToken1.setTokenStatus(JwtTokenConstant.tokenStatus.logout);
            }

            sysTokenApi.saveBatch(new EntitysPo<>(sysTokenList));



        }


        DataVo vo = DataVo.ofMsg("登录成功");
        TokenVo tokenVo =  new TokenVo();
        tokenVo.setToken(SessionUtil.getSessionId());
        vo.setData(tokenVo);
        return vo;
    }



    @Autowired
    protected SimpMessageSendingOperations simpMessageSendingOperations;

    @RequestMapping(value="/qrCodeCreate",method=RequestMethod.GET)
    @ApiOperation("创建登录二维码")
    @SneakyThrows

    public void createQrCode(HttpServletResponse response, String token){
        QrConfig config = new QrConfig(300, 300);
// 设置边距，既二维码和背景之间的边距
        // config.setMargin(3);
// 设置前景色，既二维码颜色（青色）
        //config.setForeColor(Color.CYAN.getRGB());
// 设置背景色（灰色）
        //  config.setBackColor(Color.GRAY.getRGB());

// 生成二维码到文件，也可以到流

        QrCodeUtil.generate("http://192.168.43.144:9527/#/msgLogin?token="+token, config,"png",response.getOutputStream());
    }

    @ApiOperation("注销")
    @RequestMapping(value="/logout",method=RequestMethod.POST)
    public DataVo logout() {
        String id = SessionUtil.getSessionId();
        //令牌修改
        SysToken sysToken =   iSysTokenService.newInstance();
        sysToken.setId(id);
        sysToken.setTokenStatus(JwtTokenConstant.tokenStatus.logout);
        iSysTokenService.save(sysToken);



        Subject subject =  SecurityUtils.getSubject();
        subject.logout();



        DataVo vo = DataVo.of();
        vo.setMessage("注销成功");
        RespUtil.writeCookie(ShiroCacheConstants.tokenKey,null);
        return vo;
    }

    /**
     * 向指定用户发送token授权
     * 当前用户必须登录
     */
    @RequestMapping(value="/sendToken",method=RequestMethod.POST)
    @ApiOperation("发送token给指定用户")
    public void sendToken(@RequestBody TokenPo po){
        String token = SessionUtil.getSessionId();
        Console.log(token+":授权登录");
        String key="/login/"+po.getToken();
        simpMessageSendingOperations.convertAndSend(key,"授权成功:"+token);
    }

    /**
     * 得到消息token
     * @return
     */
    @RequestMapping(value="/getLoginToken",method=RequestMethod.POST)
    @ApiOperation("得到登录token")
    public DataVo<TokenVo> getLoginToken(){
        TokenVo vo =new TokenVo();
        vo.setToken(SessionUtil.getSessionId());
        return DataVo.of(vo);
    }


    @RequestMapping(value="/mock",method=RequestMethod.POST)
    @ApiOperation("mock测试")
    @MockKey(path = "AuthUser",value = "1")
    public DataVo<TokenVo> mock(){
        return null;
    }




    @RequestMapping(value="/getUserInfo",method=RequestMethod.POST)
    @ApiOperation("获取当前用户详情")
    public DataVo<UserInfo> getUserInfo(){
        String key=ShiroCacheConstants.userKey;
        UserInfo  info =  SessionUtil.get(key);
        if(info == null){
            String username = getUsername();
            UserInfo jwtUserInfo =  userAuth.getUserInfo(username);
            //类型转换
            info =  ReflectionUtil.clone(jwtUserInfo,jwtUserInfo.getClass());
            SessionUtil.set(key,info);
        }
        return  DataVo.of(info);
    }

    protected String getUsername(){
        Subject subject =  SecurityUtils.getSubject();
        if(subject.isAuthenticated()){
            return (String)subject.getPrincipal();
        }
        ApiException.throw401("清登录");
        return null;
    }

    @RequestMapping("/test")
    public Object test(){
        HashMap params =  new HashMap<>();

        Session sesssion = SecurityUtils.getSubject().getSession();
        for (Object k : sesssion.getAttributeKeys()) {
            Object v =  sesssion.getAttribute(k);
            params.put(k,v);
        }
        params.put("1",SessionUtil.get("1"));
        params.put("2",sesssion.getAttribute("1"));
        return params;
    }


}